package org.fjsei.yewu.config;

import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.sniff.ElasticsearchNodesSniffer;
import org.elasticsearch.client.sniff.NodesSniffer;
import org.elasticsearch.client.sniff.Sniffer;
import org.elasticsearch.client.sniff.SnifferBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchProperties;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;

/**
 * 不能再用Rest Client和Transport Client了，推荐使用Java Client的API包。这里RestHighLevelClient也是淘汰中：ES8无法再用的。
 * ES对内存和CPU需求都比较大的。
 * 需要看spring-data-elasticsearch适配版本号，以及Elasticsearch自己也有适配版本号，综合考虑来升级：boot ES Java 版本；
 * 【诸多包不适配，暂无法升级 ES8.1.2版本】 new Elasticsearch client forces users to switch from using javax.json.spi.JsonProvider to jakarta.json.spi.JsonProvider. Spring Data Elasticsearch cannot enforce this switch; Spring Boot will switch to jakarta with version 3；
 * ES8对比ES7的代码变动将会非常大。JSON对象映射库，functional builders->函数式,和应用程序类的自动映射; https://juejin.cn/post/7080726607043756045
 * ES启动：代替配置文件
 * spring:
 *   data:
 *     elasticsearch:
 *       #cluster-name: docker-cluster
 *       #cluster-nodes: locahost:9300,192.168.171.3:9300
 *       #默认是http://localhost:9200
 版本兼容性  https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/
 【篡改starter适配Elasticsearch的版本】spring-boot-starter-data-elasticsearch；  https://blog.csdn.net/qq_28772075/article/details/122240942
 boot 2.6.6当前默认Elasticsearc 7.15.2；     ES8版要求java>=17版。
 ES8版本： RestHighLevelClient被抛弃，替换成ElasticsearchClient，而旧的RestClient可以继续保留。ES8版本多出个JacksonJsonpMapper();
 Enables compatibility mode that allows HLRC 7.17 to work with Elasticsearch 8.x. 遗留兼容 https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/migrate-hlrc.html
 当前spring-data-elasticsearch-4.3.3#ElasticsearchRestTemplate目前实际用了RestHighLevelClient的，看来此版本变动巨大！。
 7.17.2版本告警：WARN  org.elasticsearch.client.RestClient    company/_refresh?ignore_throttled=false&ignore_unavailable=false&expand_wildcards=open&allow_no_indices=true] :
 [299 Elasticsearch-7.17.2- "[ignore_throttled] parameter is deprecated because frozen indices have been deprecated. Consider cold or frozen tiers in place of frozen indices."]
 【差别】如何没有开启证书TLS验证，实际上无需开启@Configuration注解的。直接默认走yml配置的spring:elasticsearch:uris: http配置文件，无需额外加代码的。
 [配置毛病] ElasticsearchClientCheckConfig已经没用，导致sniffer改变http，原因是spring: elasticsearch: uris: 192.168.109.65:9200没有加https://
 除了上面这个原因；依然还是别的由头导致出现 Sniffer.Scheme.HTTP。？是.boot.autoconfigure.elasticsearch.ElasticsearchRestClientConfigurations.RestClientSnifferConfiguration#elasticsearchSniffer(.ElasticsearchProperties)毛病。
 来自这个包 org.springframework.boot:spring-boot-autoconfigure:3.3.2；
 */

@Configuration
public class ElasticsearchClientCheckConfig {
    //密码在配置文件中；生产系统和调试环境将要对接的是不一样的ES服务端主机和集群。
//    @Value("${sei.ESauthSecret:null}")
//    private String esPassword;
//    @Value("${sei.ESendUrl:localhost:9200}")
//    private String esEndUrl; httpS
    @Value("${sei.EShttpS:}")
    private Boolean useHttpS;

    private final ElasticsearchProperties properties;

    public ElasticsearchClientCheckConfig(ElasticsearchProperties properties) {
        this.properties = properties;
    }

    /*【 非常奇葩! 】 假如没有加入这一段@Bean 运行顺序变了，实际导致ClientConfiguration clientConfiguration()的运行顺序在原本配置Sniffer elasticsearchSniffer()后面部分代码执行后面才执行的。
    最终导致问题，schema都被改成http的。
    解决是：在这里自己添加这个Bean，改变了代码运行顺序，就可让Sniffer的成员变量schema可改为https的，不再是被修改为http。
    【设想】若需要2个不同的ES集群的？ 需要创建另外一个Bean ：ElasticsearchTemplate （ ）分别注入的， RestClient也要单独分开的。可ElasticsearchProperties无法配套俩个集群啊？
    实在没法拆分开的放入ES主集群。可以独立的集群ES脱离出去。
    * */
    @Bean
    @ConditionalOnMissingBean
    Sniffer elasticsearchSniffer(RestClient client, ElasticsearchProperties properties) {
        SnifferBuilder builder = Sniffer.builder(client);
        NodesSniffer hostsSniffer = new ElasticsearchNodesSniffer(
                client,
                ElasticsearchNodesSniffer.DEFAULT_SNIFF_REQUEST_TIMEOUT,
                useHttpS?  ElasticsearchNodesSniffer.Scheme.HTTPS : ElasticsearchNodesSniffer.Scheme.HTTP);
        builder.setNodesSniffer(hostsSniffer);
        PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
        Duration interval = properties.getRestclient().getSniffer().getInterval();
        map.from(interval).asInt(Duration::toMillis).to(builder::setSniffIntervalMillis);
        Duration delayAfterFailure = properties.getRestclient().getSniffer().getDelayAfterFailure();
        map.from(delayAfterFailure).asInt(Duration::toMillis).to(builder::setSniffAfterFailureDelayMillis);
        return builder.build();
    }

}


/*
ES对物理内存需求很大,改jvm.options;jvm.options.d/ 全都没用java15版本=自动调jvm堆内存。 https://www.elastic.co/guide/cn/elasticsearch/guide/current/heap-sizing.html
Elasticsearch Java API客户端是一个全新的客户端库，与旧的高级Rest客户端RestHighLevelClient（HLRC）无关。
Kibana ? elasticsearch-head 部署elasticsearch8.1.1   https://blog.csdn.net/xutengfei999/article/details/123684334
用 Docker compose 来一键部署ES集群；  https://juejin.cn/post/7082735047824015397
专门定制云版本：Elastic Cloud on Kubernetes通过ECK部署，安装在Kubernetes集群内; 自签名证书https;  https://blog.51cto.com/u_14783669/2558785
Kubernetes 搭建 Elasticsearch 7.6 集群, ES普通版的k8s集群搭建：  https://ld246.com/article/1586757433779
*/
